﻿using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using System.Xml.Serialization;

using btmerc.API.Schemas;

namespace btmerc.API
{
    public class Universe
    {
        #region Private Members
        private Eras _eras;
        private GeneralContractModifiers _generalContractModifiers;
        private GeneralContractTermAdjustments _generalContractTermAdjustments;
        private Components _components;
        private Battlemechs _battlemechs;
        private Dropships _dropships;
        private SalaryModifiers _salaryModifiers;
        private MaintenanceCosts _maintenanceCosts;
        #endregion

        public Universe(string directory) 
        {
            _components = new Components();
            _eras = new Eras();
            _battlemechs = new Battlemechs();
            _dropships = new Dropships();
            InitializeFromDirectory(directory);
        }

        public ContractGenerator GetContractGenerator(ushort year)
        {
            return new ContractGenerator(GetEra(year), _generalContractModifiers, _generalContractTermAdjustments);
        }

        #region Private Initialization Functions
        private void InitializeFromDirectory(string directory)
        {
            foreach (string filePath in Directory.GetFiles(directory, "*.xml"))
            {
                XDocument document = XDocument.Load(filePath);
                System.Type type = typeof(object);
                switch (document.Root.Name.LocalName)
                {
                    case "Battlemechs":
                        _battlemechs.Battlemech.AddRange(GetBattlemechs(filePath).Battlemech);
                        break;
                    case "Components":
                        _components.AddComponents(GetComponents(filePath));
                        break;
                    case "Dropships":
                        _dropships.Dropship.AddRange(GetDropships(filePath).Dropship);
                        break;
                    case "Era":
                        _eras.AddEra(GetEra(filePath));
                        break;
                    case "GeneralContractModifiers":
                        if (_generalContractModifiers != null)
                        {
                            throw new InvalidDataException("More than one GeneralContractModifiers file!");
                        }
                        _generalContractModifiers = GetGeneralContractModifiers(filePath);
                        break;
                    case "GeneralContractTermAdjustments":
                        if (_generalContractTermAdjustments != null)
                        {
                            throw new InvalidDataException("More than one GeneralContractTermAdjustments file!");
                        }
                        _generalContractTermAdjustments = GetGeneralContractTermAdjustments(filePath);
                        break;
                    case "MaintenaceCosts":
                        if (_maintenanceCosts != null)
                        {
                            throw new InvalidDataException("More than one MaintenaceCosts file!");
                        }
                        _maintenanceCosts = GetMaintenanceCosts(filePath);
                        break;
                    case "SalaryModifiers":
                        if (_salaryModifiers != null)
                        {
                            throw new InvalidDataException("More than one SalaryModifiers file!");
                        }
                        _salaryModifiers = GetSalaryModifiers(filePath);
                        break;
                }
                foreach (string directoryPath in Directory.GetDirectories(directory))
                {
                    InitializeFromDirectory(directoryPath);
                }
            }
        }

        private Components GetComponents(string filePath)
        {
            FileStream fileStream = new FileStream(filePath, FileMode.Open);
            XmlSerializer serializer = new XmlSerializer(typeof(Components));
            return (Components)serializer.Deserialize(fileStream);
        }

        private Era GetEra(string filePath)
        {
            FileStream fileStream = new FileStream(filePath, FileMode.Open);
            XmlSerializer serializer = new XmlSerializer(typeof(Era));
            return (Era)serializer.Deserialize(fileStream);
        }

        private GeneralContractModifiers GetGeneralContractModifiers(string filePath)
        {
            FileStream fileStream = new FileStream(filePath, FileMode.Open);
            XmlSerializer serializer = new XmlSerializer(typeof(GeneralContractModifiers));
            return (GeneralContractModifiers)serializer.Deserialize(fileStream);
        }

        private GeneralContractTermAdjustments GetGeneralContractTermAdjustments(string filePath)
        {
            FileStream fileStream = new FileStream(filePath, FileMode.Open);
            XmlSerializer serializer = new XmlSerializer(typeof(GeneralContractTermAdjustments));
            return (GeneralContractTermAdjustments)serializer.Deserialize(fileStream);
        }

        private MaintenanceCosts GetMaintenanceCosts(string filePath)
        {
            FileStream fileStream = new FileStream(filePath, FileMode.Open);
            XmlSerializer serializer = new XmlSerializer(typeof(MaintenanceCosts));
            return (MaintenanceCosts)serializer.Deserialize(fileStream);
        }

        private SalaryModifiers GetSalaryModifiers(string filePath)
        {
            FileStream fileStream = new FileStream(filePath, FileMode.Open);
            XmlSerializer serializer = new XmlSerializer(typeof(SalaryModifiers));
            return (SalaryModifiers)serializer.Deserialize(fileStream);
        }

        private Battlemechs GetBattlemechs(string filePath)
        {
            FileStream fileStream = new FileStream(filePath, FileMode.Open);
            XmlSerializer serializer = new XmlSerializer(typeof(Battlemechs));
            return (Battlemechs)serializer.Deserialize(fileStream);
        }

        private Dropships GetDropships(string filePath)
        {
            FileStream fileStream = new FileStream(filePath, FileMode.Open);
            XmlSerializer serializer = new XmlSerializer(typeof(Dropships));
            return (Dropships)serializer.Deserialize(fileStream);
        }
        #endregion

        public Schemas.Interfaces.IEra GetEra(ushort year)
        {
            return _eras.GetEra(year);
        }

        public IEnumerable<Dropship> GetAvailableDropships(ushort year)
        {
            return _dropships.Dropship.Where(d => d.IntroductionYear <= year);
        }
    }
}
